package com.sevntu.apvs.dModel.tests;

import junit.framework.Assert;

import org.apache.log4j.Logger;
import org.apache.log4j.PropertyConfigurator;
import org.junit.BeforeClass;
import org.junit.Test;

import com.sevntu.apvs.dModel.CircuitLoader;
import com.sevntu.apvs.dModel.DModel;
import com.sevntu.apvs.dModel.DModelException;

/**
 * Test class for checking circuit validation.
 * 
 * @author <a href="mailto:rd.ryly@gmail.com">Ruslan Diachenko</a>
 */
public class CircuitValidationTest {

	/** Use for log message generation */
	private static final Logger LOG = Logger.getLogger(CircuitValidationTest.class.getName());

	private CircuitLoader loader;

	private DModel dModel;

	@BeforeClass
	public static void initLog4jProperties() {
		PropertyConfigurator.configure("config/log4j.properties");
	}

	@Test
	public void test1Validation() throws DModelException {
		loader = new CircuitLoader();
		dModel = loader.getDModel("src/com/sevntu/apvs/dModel/testinputs/circuit3.xml");

		Assert.assertEquals("4OR-NOT", dModel.getElemList().get(0).name);
		Assert.assertEquals(1, dModel.getElemList().get(0).id);

		Assert.assertEquals("4OR-NOT", dModel.getElemList().get(1).name);
		Assert.assertEquals(2, dModel.getElemList().get(1).id);

		Assert.assertEquals("2OR-NOT", dModel.getElemList().get(2).name);
		Assert.assertEquals(3, dModel.getElemList().get(2).id);

		Assert.assertEquals("2OR-NOT", dModel.getElemList().get(3).name);
		Assert.assertEquals(4, dModel.getElemList().get(3).id);

		Assert.assertEquals("2OR-NOT", dModel.getElemList().get(4).name);
		Assert.assertEquals(5, dModel.getElemList().get(4).id);

		int index = 0;
		Assert.assertEquals(1, dModel.getCircuitList().get(index).getCircuitId());
		Assert.assertEquals(0, dModel.getCircuitList().get(index).getElemNumOut());
		Assert.assertEquals(1, dModel.getCircuitList().get(index).getElemContactOut());
		Assert.assertEquals(1, dModel.getCircuitList().get(index).getElemNumIn());
		Assert.assertEquals(1, dModel.getCircuitList().get(index).getElemContactIn());

		index++;
		Assert.assertEquals(1, dModel.getCircuitList().get(index).getCircuitId());
		Assert.assertEquals(0, dModel.getCircuitList().get(index).getElemNumOut());
		Assert.assertEquals(1, dModel.getCircuitList().get(index).getElemContactOut());
		Assert.assertEquals(3, dModel.getCircuitList().get(index).getElemNumIn());
		Assert.assertEquals(1, dModel.getCircuitList().get(index).getElemContactIn());

		index++;
		Assert.assertEquals(2, dModel.getCircuitList().get(index).getCircuitId());
		Assert.assertEquals(0, dModel.getCircuitList().get(index).getElemNumOut());
		Assert.assertEquals(2, dModel.getCircuitList().get(index).getElemContactOut());
		Assert.assertEquals(1, dModel.getCircuitList().get(index).getElemNumIn());
		Assert.assertEquals(2, dModel.getCircuitList().get(index).getElemContactIn());

		index++;
		Assert.assertEquals(3, dModel.getCircuitList().get(index).getCircuitId());
		Assert.assertEquals(0, dModel.getCircuitList().get(index).getElemNumOut());
		Assert.assertEquals(3, dModel.getCircuitList().get(index).getElemContactOut());
		Assert.assertEquals(1, dModel.getCircuitList().get(index).getElemNumIn());
		Assert.assertEquals(3, dModel.getCircuitList().get(index).getElemContactIn());

		index++;
		Assert.assertEquals(4, dModel.getCircuitList().get(index).getCircuitId());
		Assert.assertEquals(0, dModel.getCircuitList().get(index).getElemNumOut());
		Assert.assertEquals(4, dModel.getCircuitList().get(index).getElemContactOut());
		Assert.assertEquals(1, dModel.getCircuitList().get(index).getElemNumIn());
		Assert.assertEquals(4, dModel.getCircuitList().get(index).getElemContactIn());

		index++;
		Assert.assertEquals(4, dModel.getCircuitList().get(index).getCircuitId());
		Assert.assertEquals(0, dModel.getCircuitList().get(index).getElemNumOut());
		Assert.assertEquals(4, dModel.getCircuitList().get(index).getElemContactOut());
		Assert.assertEquals(2, dModel.getCircuitList().get(index).getElemNumIn());
		Assert.assertEquals(1, dModel.getCircuitList().get(index).getElemContactIn());

		index++;
		Assert.assertEquals(5, dModel.getCircuitList().get(index).getCircuitId());
		Assert.assertEquals(0, dModel.getCircuitList().get(index).getElemNumOut());
		Assert.assertEquals(5, dModel.getCircuitList().get(index).getElemContactOut());
		Assert.assertEquals(2, dModel.getCircuitList().get(index).getElemNumIn());
		Assert.assertEquals(2, dModel.getCircuitList().get(index).getElemContactIn());

		index++;
		Assert.assertEquals(6, dModel.getCircuitList().get(index).getCircuitId());
		Assert.assertEquals(0, dModel.getCircuitList().get(index).getElemNumOut());
		Assert.assertEquals(6, dModel.getCircuitList().get(index).getElemContactOut());
		Assert.assertEquals(2, dModel.getCircuitList().get(index).getElemNumIn());
		Assert.assertEquals(3, dModel.getCircuitList().get(index).getElemContactIn());

		index++;
		Assert.assertEquals(7, dModel.getCircuitList().get(index).getCircuitId());
		Assert.assertEquals(0, dModel.getCircuitList().get(index).getElemNumOut());
		Assert.assertEquals(7, dModel.getCircuitList().get(index).getElemContactOut());
		Assert.assertEquals(2, dModel.getCircuitList().get(index).getElemNumIn());
		Assert.assertEquals(4, dModel.getCircuitList().get(index).getElemContactIn());

		index++;
		Assert.assertEquals(7, dModel.getCircuitList().get(index).getCircuitId());
		Assert.assertEquals(0, dModel.getCircuitList().get(index).getElemNumOut());
		Assert.assertEquals(7, dModel.getCircuitList().get(index).getElemContactOut());
		Assert.assertEquals(4, dModel.getCircuitList().get(index).getElemNumIn());
		Assert.assertEquals(2, dModel.getCircuitList().get(index).getElemContactIn());

		index++;
		Assert.assertEquals(8, dModel.getCircuitList().get(index).getCircuitId());
		Assert.assertEquals(1, dModel.getCircuitList().get(index).getElemNumOut());
		Assert.assertEquals(5, dModel.getCircuitList().get(index).getElemContactOut());
		Assert.assertEquals(3, dModel.getCircuitList().get(index).getElemNumIn());
		Assert.assertEquals(2, dModel.getCircuitList().get(index).getElemContactIn());

		index++;
		Assert.assertEquals(9, dModel.getCircuitList().get(index).getCircuitId());
		Assert.assertEquals(2, dModel.getCircuitList().get(index).getElemNumOut());
		Assert.assertEquals(5, dModel.getCircuitList().get(index).getElemContactOut());
		Assert.assertEquals(4, dModel.getCircuitList().get(index).getElemNumIn());
		Assert.assertEquals(1, dModel.getCircuitList().get(index).getElemContactIn());

		index++;
		Assert.assertEquals(10, dModel.getCircuitList().get(index).getCircuitId());
		Assert.assertEquals(3, dModel.getCircuitList().get(index).getElemNumOut());
		Assert.assertEquals(3, dModel.getCircuitList().get(index).getElemContactOut());
		Assert.assertEquals(5, dModel.getCircuitList().get(index).getElemNumIn());
		Assert.assertEquals(1, dModel.getCircuitList().get(index).getElemContactIn());

		index++;
		Assert.assertEquals(11, dModel.getCircuitList().get(index).getCircuitId());
		Assert.assertEquals(4, dModel.getCircuitList().get(index).getElemNumOut());
		Assert.assertEquals(3, dModel.getCircuitList().get(index).getElemContactOut());
		Assert.assertEquals(5, dModel.getCircuitList().get(index).getElemNumIn());
		Assert.assertEquals(2, dModel.getCircuitList().get(index).getElemContactIn());

		index++;
		Assert.assertEquals(12, dModel.getCircuitList().get(index).getCircuitId());
		Assert.assertEquals(5, dModel.getCircuitList().get(index).getElemNumOut());
		Assert.assertEquals(3, dModel.getCircuitList().get(index).getElemContactOut());
		Assert.assertEquals(0, dModel.getCircuitList().get(index).getElemNumIn());
		Assert.assertEquals(8, dModel.getCircuitList().get(index).getElemContactIn());

		Assert.assertEquals(7, loader.getSchemeEntryNum());

		LOG.info("Test was successfuly complited.");
	}

	@Test(expected = DModelException.class)
	public void test2Validation() throws DModelException { // Wrong contacts
		loader = new CircuitLoader();
		dModel = loader.getDModel("src/com/sevntu/apvs/dModel/testinputs/wrong_contacts.xml");
	}

	@Test(expected = DModelException.class)
	public void test3Validation() throws DModelException { // Usage one element contact in several circuits.
		loader = new CircuitLoader();
		dModel = loader.getDModel("src/com/sevntu/apvs/dModel/testinputs/cont_in_several_circ.xml");
	}

	@Test(expected = DModelException.class)
	public void test4Validation() throws DModelException { // Fictitious contacts' IDs
		loader = new CircuitLoader();
		dModel = loader.getDModel("src/com/sevntu/apvs/dModel/testinputs/fictitious_contacts.xml");
	}

	@Test(expected = DModelException.class)
	public void test5Validation() throws DModelException { // One contact in several circuits
		loader = new CircuitLoader();
		dModel = loader.getDModel("src/com/sevntu/apvs/dModel/testinputs/cont_in_several_circ2.xml");
	}

	@Test
	public void test6Validation() throws DModelException { // feedback circuit
		loader = new CircuitLoader();
		dModel = loader.getDModel("src/com/sevntu/apvs/dModel/testinputs/feedback_in_circ.xml");

		Assert.assertEquals("2OR-NOT", dModel.getElemList().get(0).name);
		Assert.assertEquals(1, dModel.getElemList().get(0).id);

		Assert.assertEquals("2OR-NOT", dModel.getElemList().get(1).name);
		Assert.assertEquals(2, dModel.getElemList().get(1).id);

		int index = 0;
		Assert.assertEquals(1, dModel.getCircuitList().get(index).getCircuitId());
		Assert.assertEquals(2, dModel.getCircuitList().get(index).getElemNumOut());
		Assert.assertEquals(3, dModel.getCircuitList().get(index).getElemContactOut());
		Assert.assertEquals(1, dModel.getCircuitList().get(index).getElemNumIn());
		Assert.assertEquals(1, dModel.getCircuitList().get(index).getElemContactIn());

		index++;
		Assert.assertEquals(1, dModel.getCircuitList().get(index).getCircuitId());
		Assert.assertEquals(2, dModel.getCircuitList().get(index).getElemNumOut());
		Assert.assertEquals(3, dModel.getCircuitList().get(index).getElemContactOut());
		Assert.assertEquals(0, dModel.getCircuitList().get(index).getElemNumIn());
		Assert.assertEquals(2, dModel.getCircuitList().get(index).getElemContactIn());

		index++;
		Assert.assertEquals(2, dModel.getCircuitList().get(index).getCircuitId());
		Assert.assertEquals(0, dModel.getCircuitList().get(index).getElemNumOut());
		Assert.assertEquals(1, dModel.getCircuitList().get(index).getElemContactOut());
		Assert.assertEquals(1, dModel.getCircuitList().get(index).getElemNumIn());
		Assert.assertEquals(2, dModel.getCircuitList().get(index).getElemContactIn());

		index++;
		Assert.assertEquals(3, dModel.getCircuitList().get(index).getCircuitId());
		Assert.assertEquals(1, dModel.getCircuitList().get(index).getElemNumOut());
		Assert.assertEquals(3, dModel.getCircuitList().get(index).getElemContactOut());
		Assert.assertEquals(2, dModel.getCircuitList().get(index).getElemNumIn());
		Assert.assertEquals(1, dModel.getCircuitList().get(index).getElemContactIn());
	}

	@Test(expected = DModelException.class)
	public void test7Validation() throws DModelException { // One output for several circuits
		loader = new CircuitLoader();
		dModel = loader.getDModel("src/com/sevntu/apvs/dModel/testinputs/output_for_circ.xml");
	}
}
